<?php

namespace app\modules\admin\controllers;

use Yii;
use yii\filters\AccessControl;
use yii\web\Response;
use yii\db\Connection;
use app\modules\admin\components\BaseAdminController;
use app\components\Log;
use app\modules\admin\models\User;
use app\modules\admin\models\Migrations;
use yii\base\ErrorErrorException;
use yii\data\ActiveDataProvider;
use yii\data\ArrayDataProvider;

class InstallController extends BaseAdminController
{   
    // 用户权限控制
    // public function behaviors()
    // {
    //     return [
    //         'access' => [
    //             'class' => AccessControl::className(),
    //             'only' => ['drop'],
    //             'rules' => [
    //                 [
    //                     'actions' => ['drop'],
    //                     'allow' => true,
    //                     'roles' => ['@'],
    //                 ],
    //             ],
    //         ],
    //     ];
    // }

    // 登录安装
    public function actionLogin()
    {
        $install = $this->session('install');
        if ($install === true) {
            $this->redirect(['install/index']);
        }

        if (Yii::$app->request->isPost) {
            $code = Yii::$app->request->post('code');
            if ($code == 'xgate') {
                $this->session('install', true);
                Yii::$app->session->setFlash('error', '身份验证通过，请继续完成安装');
                $this->redirect(['install/index']);
            } else {
                Yii::$app->session->setFlash('error', '身份验证失败');
            }
        }

        return $this->renderPartial('login');
    }

    // 安装GUI
    // 必须先通过激活码的认证
    public function actionIndex()
    {
        $this->checkLogin();

        $config = require(Yii::$app->basePath . '/config/db.php');

        // 获取dbname
        $dsn = $config['dsn'];
        preg_match('/dbname=(.*)/', $dsn, $matches);
        $dbname = $matches[1];

        $dsn = new Connection([
		    'dsn' => 'mysql:host=localhost',
		    'username' => $config['username'],
		    'password' => $config['password'],
		    'charset' => 'utf8',
        ]);
        
        // 查询数据库是否存在
        $sql = 'SELECT * FROM information_schema.SCHEMATA where SCHEMA_NAME="' . $dbname . '"';
        $re = $dsn->createCommand($sql)->queryOne();

        if (!empty($re) && ($re['SCHEMA_NAME'] == $dbname)) {
            // 已有数据新dsn
            $dsn = new Connection([
                'dsn' => 'mysql:host=localhost;dbname=' . $dbname,
                'username' => $config['username'],
                'password' => $config['password'],
                'charset' => 'utf8',
            ]);
            // 查询数据表是否存在
            $sql = 'SHOW TABLES LIKE "%admin%"';
            $re = $dsn->createCommand($sql)->queryOne();
            if ($re === false) {
                $installed = false;
            } else {
                $installed = true;
            }
        } else {
            // 新建数据库
            // $sql = 'CREATE DATABASE `' . DB_NAME . '`;';
            // if (!$dsn->createCommand($sql)->execute()) {
            //     exit('Install Failed');
            // }
            $installed = false;
        }
        
        return $this->render('index', [
            'installed' => $installed
        ]);
    }

    // 运行安装
    // 必须先通过激活码的认证
    public function actionRunInstallation()
    {
        $this->checkLogin();

        // 1.数据库配置
        $config = require(Yii::$app->basePath . '/config/db.php');
        $dsn = $config['dsn'];
        preg_match('/dbname=(.*)/', $dsn, $matches);
        $dbname = $matches[1];

        // 2.新建数据库
        $sql = 'CREATE DATABASE `' . $dbname . '`;';
        $ddsn = new Connection([
            'dsn' => 'mysql:host=localhost',
            'username' => $config['username'],
            'password' => $config['password'],
            'charset' => 'utf8',
        ]);
        if (!$ddsn->createCommand($sql)->execute()) {
            exit('Install Failed');
        }

        // 3.连接数据库
        try {
            $dsn = new Connection([
                'dsn' => 'mysql:host=localhost;dbname=' . $dbname,
                'username' => $config['username'],
		        'password' => $config['password'],
                'charset' => 'utf8',
            ]);
        } catch (ErrorException $e) {
            exit("DB Connection Failed!");
        }

        $r = $dsn->open();

        // 4.获取原始SQL语句
        $build_sql = file_get_contents(Yii::$app->basePath . '/db/build.sql');
        
        // 5.安装数据库
        $transaction = $dsn->beginTransaction();

		try {
			$dsn->createCommand($build_sql)->execute();
			$transaction->commit();
		} catch (ErrorException $e) {
			$transaction->rollBack();
			exit("Install Failed!");
        }

        // 7.创建管理员
        if (!self::generateAdmin()) {
            throw new yii\web\ServerErrorHttpException('管理员账号生成失败');
        }
        
        // 8.显示管理员账号
		return $this->redirect(['install/index']);
    }

    // 更新数据库
    public function actionUpdate()
    {
        // 查询所有db文件夹内sql文件
        $filepath = Yii::$app->basePath . '/db';
        $files = scandir($filepath);
        $new_files = [];
        foreach($files as $v) {
            if ($v != '.' && $v != '..') {
                $new_files[]['filename'] = substr($v, 0, -4);
            }
        }
        
        // 查询所有迁移记录
        $migrations = Migrations::find()->asArray()->all();
        $fileMap = \yii\helpers\ArrayHelper::getColumn($migrations, 'filename');

        // 构建数据
        foreach ($new_files as $k => $v) {
            $filename = $v['filename'];
            if (!in_array($filename, $fileMap)) {
                $migrations[] = [
                    'id' => null,
                    'filename' => $filename,
                    'status' => 0,
                    'env' => null,
                    'migrated_at' => null,
                ];
            }
        }

        $dataProvider = new ArrayDataProvider([
            'allModels' => $migrations,
            'pagination' => [
                'pageSize' => 10,
            ],
            'sort' => [
                'attributes' => ['migrated_at'],
                'defaultOrder' => ['migrated_at' => SORT_DESC],
            ],
        ]);

        return $this->render('update', [
            'dataProvider' => $dataProvider,
        ]);
    }

    // 执行SQL文件更新数据库
    public function actionRunUpdate()
    {
        $filename = Yii::$app->request->get('id');
        if (!empty($filename) || Yii::$app->request->isPost) {
            // 读取更新文件
            if (empty($filename)) {
                $filename = Yii::$app->request->post('sql');
            }
            
            // 检查SQL文件的状态
            $migration = Migrations::find()->where(['filename' => $filename])->one();
            if ($migration) {
                Yii::$app->session->setFlash('error', '该SQL文件已经更新完成！');
                return $this->redirect(['install/update']);
            }

            // 不能输入build
            if ($filename == 'build') {
                Yii::$app->session->setFlash('error', 'build.sql为初始化文件，无法更新！');
                return $this->redirect(['install/update']);
            }

            $file = Yii::$app->basePath . '/db/' . $filename . '.sql';
            if (file_exists($file)) {
                // SQL 源文件内容
                $update_sql = file_get_contents($file);

                // 执行更新操作
                $db = Yii::$app->db;
                $transaction = $db->beginTransaction();
                try {
                    $db->createCommand($update_sql)->execute();
                    $transaction->commit();
                } catch (ErrorException $e) {
                    $transaction->rollBack();
                    exit("Update Failed!");
                }

                // SQL ERROR
                // if (empty($re)) {
                //     Yii::$app->session->setFlash('warning', 'SQL ERROR！');
                //     return $this->redirect(['install/update']);
                // }

                // 新增一条迁移记录
                $migration = new Migrations();
                $migration->filename = $filename;
                $migration->content = $update_sql;
                $migration->status = 1;
                $migration->env = YII_ENV;
                $migration->migrated_at = time();
                $migration->save();

                Yii::$app->session->setFlash('success', '更新成功');
            } else {
                Yii::$app->session->setFlash('error', '该文件已损坏或丢失！');
            }
        } else {
            Yii::$app->session->setFlash('error', 'db文件夹下未包含该文件！');
        }
        
        return $this->redirect(['install/update']);
    }

    // 查看SQL语句
    public function actionShow()
    {
        $id = Yii::$app->request->get('id');
        $file = Yii::$app->basePath . '/db/' . $id . '.sql';
        if (file_exists($file)) {
            $isDestroy = false;
            $sql = file_get_contents($file);
        } else {
            $isDestroy = true;
            $migration = Migrations::find()->where(['filename' => $id])->one();
            $sql = $migration->content;
        }

        return $this->render('show', [
            'id' => $id,
            'sql' => $sql,
            'isDestroy' => $isDestroy,
        ]);
    }

    // 删除数据库
    // 必须是登录管理员用户才可以删除
    public function actionDrop()
    {
        // $this->checkLogin();

        // $db = require(Yii::$app->basePath . '/config/db.php');

        // $dsn = new Connection([
		//     'dsn' => 'mysql:host=localhost',
		//     'username' => $db['username'],
		//     'password' => $db['password'],
		//     'charset' => 'utf8',
        // ]);

        // $sql = "DROP DATABASE IF EXISTS wechatmembercenter";

        // $dsn->createCommand($sql)->execute();

        // Yii::$app->session->destroy();

        // return $this->redirect(['install/index']);
    }

    // 检查登录状态，如果不是登录状态则跳转到登录页面
    private function checkLogin()
    {
        $install = $this->session('install');
        if ($install != true) {
            $this->redirect(['install/login']);
        }
    }

    // 生成默认管理员
    private function generateAdmin()
    {
        $admin = \app\modules\admin\models\User::findOne(1);
        if ($admin) {
            return false;
        } else {
            $admin = new \app\modules\admin\models\User();
            $admin->username = 'xgate';
            // $admin->email = 'xgate@xgate.com';
            $admin->generatePassword(123);
            $admin->generateAuthKey();
            $admin->generateAccessToken();
            return $admin->save(false);
        }
    }

}
